/**
 * 设备控制模块
 * 负责向PLC设备发送控制命令
 */
const logger = require('../utils/logger');
const EventEmitter = require('events');
const fs = require('fs');
const path = require('path');

class DeviceController extends EventEmitter {
  constructor(options = {}) {
    super();
    this.options = {
      commandLogPath: options.commandLogPath || 'logs/commands/',
      ...options
    };
    
    this.devices = new Map();
    
    // 确保命令日志目录存在
    if (!fs.existsSync(this.options.commandLogPath)) {
      fs.mkdirSync(this.options.commandLogPath, { recursive: true });
    }
  }

  /**
   * 添加设备
   * @param {string} deviceId - 设备ID
   * @param {object} adapter - PLC适配器实例
   */
  addDevice(deviceId, adapter) {
    if (this.devices.has(deviceId)) {
      logger.warn(`设备已存在，将被替换: ${deviceId}`);
    }
    
    this.devices.set(deviceId, adapter);
    logger.info(`添加设备: ${deviceId}`);
    
    return this;
  }

  /**
   * 移除设备
   * @param {string} deviceId - 设备ID
   */
  removeDevice(deviceId) {
    if (!this.devices.has(deviceId)) {
      logger.warn(`设备不存在: ${deviceId}`);
      return false;
    }
    
    this.devices.delete(deviceId);
    logger.info(`移除设备: ${deviceId}`);
    
    return true;
  }

  /**
   * 发送控制命令
   * @param {string} deviceId - 设备ID
   * @param {string} tagName - 标签名称
   * @param {any} value - 控制值
   */
  async sendCommand(deviceId, tagName, value) {
    try {
      const adapter = this.devices.get(deviceId);
      if (!adapter) {
        throw new Error(`设备不存在: ${deviceId}`);
      }
      
      if (!adapter.connected) {
        throw new Error(`设备未连接: ${deviceId}`);
      }
      
      logger.info(`发送控制命令: 设备=${deviceId}, 标签=${tagName}, 值=${value}`);
      
      // 写入标签值
      await adapter.writeTag(tagName, value);
      
      // 记录命令
      this.logCommand(deviceId, tagName, value, true);
      
      // 发出命令事件
      this.emit('command', { deviceId, tagName, value, success: true });
      
      return true;
    } catch (error) {
      logger.error(`发送控制命令失败: 设备=${deviceId}, 标签=${tagName}, 值=${value}, 错误=${error.message}`);
      
      // 记录命令
      this.logCommand(deviceId, tagName, value, false, error.message);
      
      // 发出命令错误事件
      this.emit('commandError', { deviceId, tagName, value, error });
      
      throw error;
    }
  }

  /**
   * 批量发送控制命令
   * @param {string} deviceId - 设备ID
   * @param {Array<{tagName: string, value: any}>} commands - 命令数组
   */
  async sendBatchCommands(deviceId, commands) {
    try {
      const adapter = this.devices.get(deviceId);
      if (!adapter) {
        throw new Error(`设备不存在: ${deviceId}`);
      }
      
      if (!adapter.connected) {
        throw new Error(`设备未连接: ${deviceId}`);
      }
      
      logger.info(`发送批量控制命令: 设备=${deviceId}, 命令数量=${commands.length}`);
      
      const results = [];
      
      for (const cmd of commands) {
        try {
          await adapter.writeTag(cmd.tagName, cmd.value);
          
          // 记录命令
          this.logCommand(deviceId, cmd.tagName, cmd.value, true);
          
          results.push({
            tagName: cmd.tagName,
            value: cmd.value,
            success: true
          });
        } catch (error) {
          logger.error(`批量命令中的单个命令失败: 设备=${deviceId}, 标签=${cmd.tagName}, 值=${cmd.value}, 错误=${error.message}`);
          
          // 记录命令
          this.logCommand(deviceId, cmd.tagName, cmd.value, false, error.message);
          
          results.push({
            tagName: cmd.tagName,
            value: cmd.value,
            success: false,
            error: error.message
          });
        }
      }
      
      // 发出批量命令事件
      this.emit('batchCommand', { deviceId, commands, results });
      
      return results;
    } catch (error) {
      logger.error(`发送批量控制命令失败: 设备=${deviceId}, 错误=${error.message}`);
      
      // 发出批量命令错误事件
      this.emit('batchCommandError', { deviceId, commands, error });
      
      throw error;
    }
  }

  /**
   * 记录控制命令
   * @param {string} deviceId - 设备ID
   * @param {string} tagName - 标签名称
   * @param {any} value - 控制值
   * @param {boolean} success - 是否成功
   * @param {string} errorMessage - 错误信息
   */
  logCommand(deviceId, tagName, value, success, errorMessage = null) {
    try {
      const timestamp = new Date().toISOString();
      const date = timestamp.split('T')[0];
      const deviceDir = path.join(this.options.commandLogPath, deviceId);
      
      // 确保设备命令日志目录存在
      if (!fs.existsSync(deviceDir)) {
        fs.mkdirSync(deviceDir, { recursive: true });
      }
      
      const filePath = path.join(deviceDir, `${date}.json`);
      let fileData = [];
      
      // 如果文件已存在，读取现有数据
      if (fs.existsSync(filePath)) {
        const fileContent = fs.readFileSync(filePath, 'utf8');
        try {
          fileData = JSON.parse(fileContent);
        } catch (error) {
          logger.error(`解析命令日志文件失败: ${filePath}, ${error.message}`);
          fileData = [];
        }
      }
      
      // 添加新命令记录
      fileData.push({
        timestamp,
        tagName,
        value,
        success,
        errorMessage
      });
      
      // 写入文件
      fs.writeFileSync(filePath, JSON.stringify(fileData, null, 2), 'utf8');
      logger.debug(`记录命令到文件: ${filePath}`);
    } catch (error) {
      logger.error(`记录命令失败: ${deviceId}, ${error.message}`);
    }
  }

  /**
   * 读取命令历史
   * @param {string} deviceId - 设备ID
   * @param {string} date - 日期 (YYYY-MM-DD)
   */
  readCommandHistory(deviceId, date) {
    try {
      const filePath = path.join(this.options.commandLogPath, deviceId, `${date}.json`);
      
      if (!fs.existsSync(filePath)) {
        logger.warn(`命令历史文件不存在: ${filePath}`);
        return [];
      }
      
      const fileContent = fs.readFileSync(filePath, 'utf8');
      return JSON.parse(fileContent);
    } catch (error) {
      logger.error(`读取命令历史失败: ${deviceId}, ${date}, ${error.message}`);
      return [];
    }
  }
}

module.exports = DeviceController;
